package com.jc.repository.mapper.intercepor;

import com.jc.idGen.gen.IdGenerator;
import com.jc.repository.domain.CanonicalDomain;
import com.jc.repository.shard.database.PartitionContext;
import com.jc.repository.shard.database.PartitionedTable;
import com.jc.repository.shard.table.SegmentTable;
import com.jc.utils.ArrayUtils;
import com.jc.utils.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Date;


@Component
@Aspect
public class MapperInterceptor {

	@Autowired
	IdGenerator zkIdGenerator;
		
	@Before("execution(* com.jc..mapper..*.*(..))")
	public void testBefore(JoinPoint point){
		MethodSignature method =(MethodSignature) point.getSignature();
		try {
			before(method.getMethod(),point.getArgs(),point.getThis());
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
	
	public void before(Method method, Object[] objs, Object object) throws Throwable {
		Class<?> entityClass = method.getDeclaringClass();

		CanonicalDomain domain = null;
		if (ArrayUtils.isNotEmpty(objs)) {
			for (Object obj : objs) {
				if (obj instanceof CanonicalDomain) {
					domain = (CanonicalDomain) obj;
					break;
				}
			}
		}

		if (domain != null) {
			// 数据库创建和更新时间添加
			if (method.getName().startsWith("insert")) {
				domain.setCreatedAt(new Date());
				domain.setUpdatedAt(new Date());
				Long id = zkIdGenerator.genLongId();
				domain.setId(id);
			} else if (method.getName().startsWith("update")) {
				domain.setUpdatedAt(new Date());
			}

			// 分表主键补全
			if (entityClass.isAnnotationPresent(SegmentTable.class)) {
				SegmentTable segmentTable = entityClass.getAnnotation(SegmentTable.class);
				if (segmentTable != null && StringUtils.isNotEmpty(segmentTable.shardKey())
						&& method.getName().startsWith("insert")) {
					for (Object obj : objs) {
						if (obj instanceof CanonicalDomain) {
							Class<?> clazz = (Class<?>) ((ParameterizedType) obj.getClass().getGenericSuperclass())
									.getActualTypeArguments()[0];
							/**
							if (domain.getId() == null) {
								long id = shardingKeyDao.getShardKey(segmentTable.shardKey());
								if (clazz.isAssignableFrom(Integer.class)) {
									domain.setId(Integer.valueOf(String.valueOf(id)));
								} else {
									domain.setId(id);
								}
							}**/
						}
					}
				}
			}
		}

		// 数据源选择
		if (entityClass.isAnnotationPresent(PartitionedTable.class)) {
			PartitionedTable partitionedTable = entityClass.getAnnotation(PartitionedTable.class);
			if (partitionedTable != null) {
				PartitionContext.set(partitionedTable.value());
			}
		} else {
			PartitionContext.set("default");
		}
	}
}
